// This file is part of OpenMeca, an easy software to do mechanical simulation.
//
// Author(s)    :  - Damien ANDRE  <openmeca@gmail.com>
//
// Copyright (C) 2012 Damien ANDRE
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.


#ifndef OpenMeca_Core_UserItem_hpp
#define OpenMeca_Core_UserItem_hpp

#include <string>
#include <QIcon>
#include <QTreeWidgetItem>

#include "OpenMeca/Core/Item.hpp"
#include "OpenMeca/Core/SetOf.hpp"
#include "OpenMeca/Core/AutoRegister.hpp"
#include "OpenMeca/Gui/MainTreeItem.hpp"
#include "OpenMeca/Gui/SecondaryTreeItem.hpp"
#include "OpenMeca/Geom/Frame.hpp"
#include "OpenMeca/Util/Color.hpp"


namespace OpenMeca
{
  namespace Gui
  {
    class MainTreeItem;
    class SecondaryTreeItem;
  }

  namespace Item
  {
    class Body;
  }

  namespace Core
  {
    
    class UserItem : public Item, public AutoRegister<UserItem>
    {
      

    public:
      static void UnselectAll();

    public:    
      UserItem(const std::string strType, QTreeWidgetItem& parent);
      virtual ~UserItem();
      
      void AddChildItem(UserItem&);
      void EraseChildItem(UserItem&);

      const Gui::MainTreeItem& GetMainTreeItem() const;
      Gui::MainTreeItem& GetMainTreeItem();
      
      const std::string& GetName() const;
      std::string& GetName();
      
      virtual void Update();
      QIcon& GetIcon();
      const QIcon& GetIcon() const;
      const SetOf<UserItem>& GetDependentItems() const;
      SetOf<UserItem>& GetDependentItems();

      SetOfBase<UserItem> GetAllDependentItems(); // recursive computation of dependant item


      void ChangeParentTreeItem(QTreeWidgetItem& parent);

      void Select();
      void UnSelect(); 
      bool IsSelected() const;
      void SetIsSelected(bool);
      void MainTreeItemIsDeleted();

      virtual const Geom::Frame<_3D>& GetReferenceFrame() const {assert(0);}

      virtual const Geom::Frame<_3D>& GetFrame() const {assert(0);}
      virtual const Util::Color& GetColor() const {assert(0);}
      virtual Util::Color& GetColor() {assert(0);}

      virtual const OpenMeca::Item::Body& GetBody() const {assert(0);}
      virtual OpenMeca::Item::Body& GetBody() {assert(0);}
    
    protected:
      virtual void UpdateIcon() = 0;
      virtual SetOfBase<UserItem> GetAssociatedSelectedItem(); //Default return empty set

    private :
      std::string name_;
      QIcon icon_;
      Gui::MainTreeItem* mainTreeItem_;
      std::vector<Gui::SecondaryTreeItem*> secondaryTreeItems_;
      SetOf<UserItem> dependentItems_;
      SetOf<UserItem> parentsItems_;
      bool isSelected_;

    private :
      UserItem();                            //Not Allowed
      UserItem(const UserItem&);             //Not Allowed
      UserItem& operator=(const UserItem&);  //Not Allowed
      
      void ConcatenateDependentItems(SetOfBase<UserItem>&);

      friend class boost::serialization::access;
      template<class Archive>
      void serialize(Archive & ar, const unsigned int);
      
    }; 

    template<class Archive>
    inline void
    UserItem::serialize(Archive & ar, const unsigned int)
    {
      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Item);
      ar & BOOST_SERIALIZATION_NVP(name_);
    }
    
    

  }
}


#endif
